from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QListView, QPushButton, QLabel, QLineEdit, QFormLayout, QTextBrowser, QCheckBox, QFileDialog
from PySide6.QtCore import Qt, QTimer, QStringListModel, QThread, Signal, Slot, QObject, QMutex
from PySide6.QtGui import QTextCursor, QIcon
from client import Client

from util.util_system import SystemUtil

import resource


class ClientGUI(QMainWindow):
    # 定义信号
    log_signal = Signal(str)
    search_signal = Signal(dict)
    modify_signal = Signal(dict)
    time_set_signal = Signal(dict)

    def __init__(self):
        super().__init__()
        # 初始化客户端
        self.client = Client(self.callabck_search, self.callabck_modify, self.callabck_time_set, None)
        self.device_list = []
        self.list_model = QStringListModel()
        self.initUI()
        self.current_device = None
        # 连接信号与槽
        self.log_signal.connect(self.handle_log)
        self.search_signal.connect(self.handle_search)
        self.modify_signal.connect(self.handle_modify)
        self.time_set_signal.connect(self.handle_time_set)
        self.client.start()

    def initUI(self):
        self.setWindowTitle("设备查找工具")
        self.setWindowIcon(QIcon(":/favicon.ico"))
        self.resize(700, 600)
        # 应用样式表
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
                color: #333333;
            }
            QGroupBox {
                border: 1px solid #e0e0e0;
                border-radius: 4px;
                padding-top: 15px;
                font-size: 14px;
                font-weight: bold;
                background-color: #ffffff;
                color: #333333;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                top: 5px;
                left: 5px;
                padding: 0 3px;
            }
            QPushButton {
                background-color: #4a90e2;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                font-weight: bold;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #3a7bc8;
            }
            QPushButton:pressed {
                background-color: #2a6ab4;
            }
            QPushButton:disabled {
                background-color: #cccccc;
                color: #999999;
            }
            QLineEdit {
                padding: 8px;
                border: 1px solid #e0e0e0;
                border-radius: 4px;
                background-color: #ffffff;
                color: #333333;
                selection-background-color: #4a90e2;
            }
            QLineEdit:hover {
                border: 1px solid #4a90e2;
            }
            QLineEdit:focus {
                border: 1px solid #4a90e2;
            }
            QTextBrowser {
                background-color: #ffffff;
                border: 1px solid #e0e0e0;
                border-radius: 4px;
                font-family: Consolas, monospace;
                font-size: 12px;
                color: #333333;
                padding: 8px;
            }
            QLabel {
                font-weight: bold;
                color: #333333;
                font-size: 13px;
            }
            QListView {
                background-color: #ffffff;
                border: 1px solid #e0e0e0;
                border-radius: 4px;
                color: #333333;
                padding: 8px;
            }
            QListView::item {
                padding: 8px;
            }
        """)

        # 主布局
        main_layout = QVBoxLayout()
        main_layout.setSpacing(5)  # 减少主布局间距

        # 设备区域（水平排布）
        device_layout = QHBoxLayout()
        device_layout.setSpacing(5)  # 减少设备区域间距

        # 左侧设备列表
        left_group = QGroupBox("设备列表")
        left_layout = QVBoxLayout()
        left_layout.setSpacing(5)  # 减少左侧布局间距
        self.list_view = QListView()
        self.refresh_button = QPushButton("刷新设备列表")
        left_layout.addWidget(self.list_view)
        left_layout.addWidget(self.refresh_button)
        left_group.setLayout(left_layout)
        device_layout.addWidget(left_group)
        self.list_view.setModel(self.list_model)
        self.list_view.clicked.connect(self.on_list_item_clicked)

        # 右侧设备详情
        detail_group = QGroupBox("设备详情")
        detail_layout = QVBoxLayout()
        detail_layout.setSpacing(5)  # 减少右侧布局间距

        # 表单布局
        form_layout = QFormLayout()
        form_layout.setLabelAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter)
        form_layout.setFormAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignVCenter)
        form_layout.setSpacing(5)  # 减少表单布局间距

        self.name_edit = QLineEdit()
        self.serial_edit = QLineEdit()
        self.serial_edit.setReadOnly(True)
        self.serial_edit.setDisabled(True)
        self.note_edit = QLineEdit()
        self.ip_edit = QLineEdit()
        self.ip_edit.setInputMask('000.000.000.000;_')
        self.ip_edit.setPlaceholderText("192.168.1.1")
        self.mask_edit = QLineEdit()
        self.mask_edit.setInputMask('000.000.000.000;_')
        self.mask_edit.setPlaceholderText("255.255.255.0")
        self.gateway_edit = QLineEdit()
        self.gateway_edit.setInputMask('000.000.000.000;_')
        self.gateway_edit.setPlaceholderText("192.168.1.254")
        self.ntp_url_edit = QLineEdit()

        form_layout.addRow("名称", self.name_edit)
        form_layout.addRow("序列号", self.serial_edit)
        form_layout.addRow("备注", self.note_edit)
        form_layout.addRow("IP地址", self.ip_edit)
        form_layout.addRow("子网掩码", self.mask_edit)
        form_layout.addRow("网关", self.gateway_edit)
        form_layout.addRow("ntp", self.ntp_url_edit)

        detail_layout.addLayout(form_layout)

        # 本地时间布局
        local_time_layout = QHBoxLayout()
        local_time_layout.setSpacing(5)  # 减少本地时间布局间距
        self.local_time_edit = QLineEdit()
        self.local_time_edit.setReadOnly(True)
        self.local_time_edit.setDisabled(True)
        local_time_layout.addWidget(QLabel("本地时间"))
        local_time_layout.addWidget(self.local_time_edit)
        detail_layout.addLayout(local_time_layout)
        self.timer_local_time = QTimer(self)
        self.timer_local_time.timeout.connect(self.on_timer_event_local_time)
        self.timer_local_time.start(1000)
        self.on_timer_event_local_time()

        # 同步时间按钮
        self.sync_button = QPushButton("手动同步本地时间到设备")
        detail_layout.addWidget(self.sync_button)
        self.sync_button.setEnabled(False)

        # 提交修改按钮
        self.submit_button = QPushButton("提交修改信息到设备")
        detail_layout.addWidget(self.submit_button)
        self.submit_button.setEnabled(False)

        detail_group.setLayout(detail_layout)
        device_layout.addWidget(detail_group)

        main_layout.addLayout(device_layout)

        # 日志输出组（置于底部）
        log_group = QGroupBox("日志输出")
        log_layout = QVBoxLayout()
        log_layout.setSpacing(5)  # 减少日志输出组间距
        
        self.log_browser = QTextBrowser()
        self.log_browser.setMinimumHeight(200)
        log_layout.addWidget(self.log_browser)

        # 按钮布局
        button_layout = QHBoxLayout()
        button_layout.setSpacing(5)  # 减少按钮布局间距
        
        self.clear_log_button = QPushButton("清空日志")
        self.clear_log_button.clicked.connect(self.log_browser.clear)
        button_layout.addWidget(self.clear_log_button)
        
        self.export_log_button = QPushButton("导出日志")
        self.export_log_button.clicked.connect(self.on_export_log_clicked)
        button_layout.addWidget(self.export_log_button)
        
        log_layout.addLayout(button_layout)
        log_group.setLayout(log_layout)
        main_layout.addWidget(log_group)

        # 设置中心部件
        central_widget = QWidget()
        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

        # 绑定按钮事件
        self.refresh_button.clicked.connect(self.on_refresh_clicked)
        self.sync_button.clicked.connect(self.on_sync_time_clicked)
        self.submit_button.clicked.connect(self.on_submit_clicked)

    def showEvent(self, a0):
        self.timer_local_time.start(1000)
        return super().showEvent(a0)
    
    def closeEvent(self, a0):
        self.timer_local_time.stop()
        return super().closeEvent(a0)
    
    def on_timer_event_local_time(self):
        self.local_time_edit.setText(SystemUtil.timestamp_to_string(SystemUtil.get_current_timestamp_ms()))

    def on_refresh_clicked(self):
        try:
            self.device_list.clear()
            self.list_model.setStringList([])
            self.name_edit.setText("")
            self.serial_edit.setText("")
            self.note_edit.setText("")
            self.ip_edit.setText("")
            self.ntp_url_edit.setText("")
            self.mask_edit.setText("")
            self.gateway_edit.setText("")
            self.submit_button.setEnabled(False)
            self.sync_button.setEnabled(False)

            self.client.sendDeviceSearch()
            self.callabck_log("已发送设备搜索请求")
        except Exception as e:
            self.callabck_log(f"刷新设备列表异常: {e}")

    def on_export_log_clicked(self):
        try:
            log_content = self.log_browser.toPlainText()
            if not log_content:
                self.callabck_log("日志内容为空，无需导出")
                return

            file_path, _ = QFileDialog.getSaveFileName(self, "导出日志", f"log-{SystemUtil.timestamp_to_string_for_path()}.txt", "文本文件 (*.txt);;所有文件 (*)")
            if file_path:
                with open(file_path, "w", encoding="utf-8") as file:
                    file.write(log_content)
                self.callabck_log(f"日志已导出到: {file_path}")
        except Exception as e:
            self.callabck_log(f"导出日志异常: {e}")

    def on_sync_time_clicked(self):
        try:
            if self.current_device:
                self.client.sendDeviceTimeSet(self.current_device["serial"], SystemUtil.get_current_timestamp_ms())
        except Exception as e:
            self.callabck_log(f"同步时间异常: {e}")

    def callabck_log(self, log):
        try:
            self.log_signal.emit(log)
        except Exception as e:
            print(f"日志回调异常: {e}")

    def handle_log(self, log):
        self.log_browser.append(f"[{SystemUtil.timestamp_to_string_ms(SystemUtil.get_current_timestamp_ms())}] - {log}")
        self.log_browser.verticalScrollBar().setValue(self.log_browser.verticalScrollBar().maximum())

    def on_list_item_clicked(self, index):
        self.current_device = self.device_list[index.row()]
        self.name_edit.setText(self.current_device["name"])
        self.serial_edit.setText(self.current_device["serial"])
        self.note_edit.setText(self.current_device["remark"])
        self.ip_edit.setText(self.current_device["ip"])
        self.mask_edit.setText(self.current_device["submask"])
        self.gateway_edit.setText(self.current_device["gateway"])
        self.ntp_url_edit.setText(self.current_device["ntp_url"])
        self.submit_button.setEnabled(True)
        self.sync_button.setEnabled(True)

    def on_submit_clicked(self):
        name = self.name_edit.text()
        serial = self.serial_edit.text()
        note = self.note_edit.text()
        ip = self.ip_edit.text()
        submask = self.mask_edit.text()
        gateway = self.gateway_edit.text()
        ntp_url = self.ntp_url_edit.text()
        # 验证必填字段
        if not name or not serial or not ip or not submask or not gateway:
            self.callabck_log("错误：名称、序列号、IP地址、子网掩码和网关不能为空！")
            return

        # 验证IP地址、子网掩码和网关格式
        def is_valid_ip(ip_str):
            parts = ip_str.split('.')
            if len(parts) != 4:
                return False
            for part in parts:
                try:
                    num = int(part)
                    if num < 0 or num > 255:
                        return False
                except ValueError:
                    return False
            return True

        if not is_valid_ip(ip):
            self.callabck_log(f"错误：IP地址 {ip} 格式无效！")
            return

        if not is_valid_ip(submask):
            self.callabck_log(f"错误：子网掩码 {submask} 格式无效！")
            return

        if not is_valid_ip(gateway):
            self.callabck_log(f"错误：网关 {gateway} 格式无效！")
            return
        
        if (self.current_device["serial"] != serial or 
            self.current_device["name"] != name or 
            self.current_device["remark"] != note or 
            self.current_device["ip"] != ip or 
            self.current_device["submask"] != submask or
            self.current_device["ntp_url"] != ntp_url or
            self.current_device["gateway"] != gateway):
            self.client.sendDeviceModify(serial, name, note, ip, submask, gateway, ntp_url)
            self.callabck_log("已发送修改请求")
            self.on_refresh_clicked()
        else:
            self.callabck_log("未修改任何信息，无需提交！")

    def callabck_search(self, data):
        try:
            self.callabck_log(f"收到搜索响应: {data}")
            self.search_signal.emit(data)
        except Exception as e:
            self.callabck_log(f"搜索回调异常: {e}")

    def handle_search(self, data):
        # 检查设备是否已存在
        existing_device = next((device for device in self.device_list if device["serial"] == data["serial"]), None)
        if not existing_device:
            self.device_list.append(data)
            
        # 更新列表视图
        device_names = [f"{device["name"]}@{device["serial"]}@{device["ip"]}" for device in self.device_list]
        self.list_model.setStringList(device_names)
        
    def callabck_modify(self, data):
        try:
            self.callabck_log(f"收到修改响应: {data}")
            self.modify_signal.emit(data)
        except Exception as e:
            self.callabck_log(f"修改回调异常: {e}")

    def handle_modify(self, data):
        pass


    def callabck_time_set(self, data):
        try:
            self.callabck_log(f"收到设置时间响应: {data}")
            self.time_set_signal.emit(data)
        except Exception as e:
            self.callabck_log(f"设置时间回调异常: {e}")

    def handle_time_set(self, data):
        pass

if __name__ == "__main__":
    app = QApplication([])
    client = ClientGUI()
    client.show()
    app.exec()
